package lrscp.lib.swt.control;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import lrscp.lib.Common;
import lrscp.lib.swt.SwtUtils;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

public class LogView extends Composite {
    static final Pattern PAT_LOG = Pattern.compile("([D|I|E]) \\w+: \\w+");

    private static final String LOGD = "D";
    private static final String LOGI = "I";
    private static final String LOGE = "E";

    private static final String STR_AUTO_SCROLL = "scroll";

    public static final String STR_COLUMN_LEVEL = "lvl";
    public static final String STR_COLUMN_TAG = "tag";
    public static final String STR_COLUMN_CONTENT = "content";

    private static final String[] STRS_COLUMN_NAME = new String[] { STR_COLUMN_LEVEL,
            STR_COLUMN_TAG, STR_COLUMN_CONTENT };
    private static final String[] STRS_LOG_LEVELS = new String[] { "debug", "info", "error" };

    private int[] columnWidth = null;

    private Config cfg = null;;

    Table table;

    private Composite parent;

    public LogView(Composite parent, int style) {
        super(parent, style);
        setupConfig();

        setLayout(new GridLayout(2, false));

        table = new Table(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI
                | SWT.FULL_SELECTION);
        table.setHeaderVisible(true);
        GridData data = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 10);
        data.widthHint = cfg.tableWidth;
        data.heightHint = cfg.tableHeight;
        table.setLayoutData(data);

        for (int i = 0; i < STRS_COLUMN_NAME.length; i++) {
            TableColumn tc = new TableColumn(table, 0);
            tc.setText(STRS_COLUMN_NAME[i]);
            tc.setWidth(cfg.getTableColWidth(STRS_COLUMN_NAME[i]));
        }

        Button butnAutoScroll = new Button(this, SWT.CHECK);
        butnAutoScroll.setText(STR_AUTO_SCROLL);
        butnAutoScroll.setSelection(cfg.autoScroll);
        butnAutoScroll.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                append(null, null, null);
            }
        });

        Combo levelCb = new Combo(this, 0);
        levelCb.setItems(STRS_LOG_LEVELS);
        levelCb.setText(cfg.level);
    }

    private void setupConfig() {
        cfg = new Config();
    }

    static class Config {
        private static final String DEFAULT_LOG_LEVEL = LOGD;
        private static final int DEFAULT_TABLE_HEIGHT = 300;
        private static final int DEFAULT_TABLE_WIDTH = 500;

        int tableWidth = DEFAULT_TABLE_WIDTH;
        int tableHeight = DEFAULT_TABLE_HEIGHT;
        int colLevelWidth = 10;
        int colTagWidth = 20;
        int colContentWidth = 200;
        boolean autoScroll = false;
        String level = DEFAULT_LOG_LEVEL;

        public int getTableColWidth(String columnName) {
            if (columnName.equals(STR_COLUMN_LEVEL)) {
                return colLevelWidth;
            }
            if (columnName.equals(STR_COLUMN_TAG)) {
                return colTagWidth;
            }
            if (columnName.equals(STR_COLUMN_CONTENT)) {
                return colContentWidth;
            }
            return 10;
        }
        
        public static void restore(String dbFile){
//            Config cfg = new Config();
//            try {
//                Connection con = DbUtils.sqliteGetConnection(dbFile);
//                Statement sql = con.createStatement();
//                
//                cfg.tableWidth = sql.executeQuery("select * from ");
//            } catch (ClassNotFoundException e) {
//                e.printStackTrace();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
        }
        
        public static int getInt(Statement sql, String table, String key) throws SQLException{
//            String s = String.format("select * from %1s where key='%2s'", table, key);
//            Log.i("query:" + s);
//            ResultSet rs = sql.executeQuery(s);
//            if(rs.next()) return rs.getInt("value");
//            return 0;
            return 0;
        }
    }

    public void asyncAppend(String log) {
        Matcher matcher = PAT_LOG.matcher(log);

        String level = null;
        String tag = null;
        String content = null;

        if (matcher.find()) {
            level = matcher.group(1);
            tag = matcher.group(2);
            content = matcher.group(3);
        } else {
            content = log;
        }

        asyncAppend(level, tag, content);
    }

    public void asyncAppend(final String level, final String tag, final String content) {
        if (Thread.currentThread() != Display.getDefault().getThread()) {
            getDisplay().asyncExec(new Runnable() {
                @Override
                public void run() {
                    append(level, tag, content);
                }
            });
        } else {
            append(level, tag, content);
        }
    }

    private void append(String level, String tag, String content) {
        TableItem item = new TableItem(table, 0);
        item.setText(new String[] { level, tag, content });
        item.setForeground(getLevelColor(level));
        if (cfg.autoScroll)
            scrollDown();
    }

    private void scrollDown() {}

    private Color getLevelColor(String level) {
        Color c = getDisplay().getSystemColor(SWT.COLOR_BLACK);
        if (level == null)
            return c;
        if (level.equals(LOGI)) {
            c = getDisplay().getSystemColor(SWT.COLOR_GREEN);
        } else if (level.equals(LOGE)) {
            c = getDisplay().getSystemColor(SWT.COLOR_RED);
        }
        return c;
    }

    void setScrollable(boolean scrollable) {
        cfg.autoScroll = scrollable;
    }

    void setBufferSize(long size) {

    }

    void setLogLevel(String level) {

    }

    public static void main(String[] args) {
        Shell shell = new Shell();
        shell.setLayout(new GridLayout(1, false));
        final LogView v = new LogView(shell, 0);
        new Thread(new Runnable() {
            @Override
            public void run() {
                int i = 1;
                while (true) {
                    i++;
                    v.asyncAppend("hello");
                    v.asyncAppend(LOGD, "tag" + i, "test" + i);
                    v.asyncAppend(LOGI, "tag" + i, "test" + i);
                    v.asyncAppend(LOGE, "tag" + i, "test" + i);
                    Common.sleep(1000);
                }
            }
        }).start();
        SwtUtils.openShell(shell);
    }
}
